/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/*
 * ConnectPanel.java
 *
 * Created on 21-mrt-2010, 20:49:41
 */
package nl.lemval.nododue.tabs;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Collection;
import javax.swing.ComboBoxModel;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JPanel;
import javax.swing.Timer;
import nl.lemval.nododue.NodoDueManager;
import nl.lemval.nododue.NodoDueManagerView;
import nl.lemval.nododue.Options;
import nl.lemval.nododue.cmd.CommandInfo;
import nl.lemval.nododue.cmd.CommandInfo.Name;
import nl.lemval.nododue.cmd.CommandLoader;
import nl.lemval.nododue.cmd.NodoCommand;
import nl.lemval.nododue.component.ArduinoImagePanel;
import nl.lemval.nododue.util.NodoSetting;
import nl.lemval.nododue.util.NodoSettingRetriever;
import nl.lemval.nododue.util.Wire;
import nl.lemval.nododue.util.Wire.Type;
import nl.lemval.nododue.util.WireList;
import nl.lemval.nododue.component.WireGraphPanel;
import nl.lemval.nododue.util.InputRange;
import nl.lemval.nododue.util.SerialCommunicator;
import nl.lemval.nododue.util.WireData;
import org.jdesktop.application.Action;
import org.jdesktop.application.Task;
import org.jdesktop.application.TaskService;

/**
 *
 * @author Michael
 */
public class MonitorPanel extends NodoBasePanel {

    private Timer refreshTimer = null;
    private Wire selectedWire = null;
    private WireList allWires = new WireList();
    private RefreshTask refreshTask = null;
    private ComboBoxModel typeSelectionModel;

    public MonitorPanel(NodoDueManagerView view) {
        super(view);

        Object[] items = Options.getInstance().getInputRanges();
        typeSelectionModel = new DefaultComboBoxModel(items);

        initComponents();

        rrSlider.setValue(20);
        refreshRateValueChanged(null);

        if (NodoDueManager.isLinux()) {
            rrSlider.setPaintLabels(true);
            marginSlider.setPaintLabels(true);
            thresholdSlider.setPaintLabels(true);
        }
        thresholdSlider.setEnabled(false);
        thresholdValue.setEnabled(false);
        marginSlider.setEnabled(false);
        marginValue.setEnabled(false);
        typeSelection.setEnabled(false);

        updateTooltips();

        InputRange ir = (InputRange) typeSelection.getSelectedItem();
        allWires.get(1, Type.Input).setSignalType(ir);
        allWires.get(2, Type.Input).setSignalType(ir);
        allWires.get(3, Type.Input).setSignalType(ir);
        allWires.get(4, Type.Input).setSignalType(ir);
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        inoutputGroup = new javax.swing.JPanel();
        outputPanel = new javax.swing.JPanel();
        output4 = new javax.swing.JLabel();
        output3 = new javax.swing.JLabel();
        output2 = new javax.swing.JLabel();
        output1 = new javax.swing.JLabel();
        jPanel2 = new javax.swing.JPanel();
        input1 = new javax.swing.JLabel();
        input2 = new javax.swing.JLabel();
        input3 = new javax.swing.JLabel();
        input4 = new javax.swing.JLabel();
        imagePanel = createImagePanel();
        graphGroup = new javax.swing.JPanel();
        graphTitle = new javax.swing.JLabel();
        lineGraph = new WireGraphPanel();
        thresholdPanel = new javax.swing.JPanel();
        thresholdLabel = new javax.swing.JLabel();
        thresholdSlider = new javax.swing.JSlider();
        thresholdValue = new javax.swing.JTextField();
        marginPanel = new javax.swing.JPanel();
        marginLabel = new javax.swing.JLabel();
        marginSlider = new javax.swing.JSlider();
        marginValue = new javax.swing.JTextField();
        wireCheck = new javax.swing.JCheckBox();
        typePanel = new javax.swing.JPanel();
        typeLabel = new javax.swing.JLabel();
        typeSelection = new javax.swing.JComboBox();
        refreshGroup = new javax.swing.JPanel();
        jPanel1 = new javax.swing.JPanel();
        rrCheck = new javax.swing.JCheckBox();
        rrSlider = new javax.swing.JSlider();
        rrValue = new javax.swing.JTextField();
        rrLabel = new javax.swing.JLabel();
        jPanel3 = new javax.swing.JPanel();
        ververs = new javax.swing.JButton();

        setName("Form"); // NOI18N

        org.jdesktop.application.ResourceMap resourceMap = org.jdesktop.application.Application.getInstance(nl.lemval.nododue.NodoDueManager.class).getContext().getResourceMap(MonitorPanel.class);
        inoutputGroup.setBorder(javax.swing.BorderFactory.createTitledBorder(resourceMap.getString("inoutputGroup.border.title"))); // NOI18N
        inoutputGroup.setName("inoutputGroup"); // NOI18N
        inoutputGroup.setLayout(new org.netbeans.lib.awtextra.AbsoluteLayout());

        outputPanel.setName("outputPanel"); // NOI18N

        output4.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        output4.setText(resourceMap.getString("output4.text")); // NOI18N
        output4.setBorder(javax.swing.BorderFactory.createEtchedBorder());
        output4.setName("output4"); // NOI18N
        output4.setPreferredSize(new java.awt.Dimension(14, 18));
        output4.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                outputWireMouseClicked(evt);
            }
        });
        outputPanel.add(output4);

        output3.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        output3.setText(resourceMap.getString("output3.text")); // NOI18N
        output3.setBorder(javax.swing.BorderFactory.createEtchedBorder());
        output3.setName("output3"); // NOI18N
        output3.setPreferredSize(new java.awt.Dimension(14, 18));
        output3.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                outputWireMouseClicked(evt);
            }
        });
        outputPanel.add(output3);

        output2.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        output2.setText(resourceMap.getString("output2.text")); // NOI18N
        output2.setBorder(javax.swing.BorderFactory.createEtchedBorder());
        output2.setName("output2"); // NOI18N
        output2.setPreferredSize(new java.awt.Dimension(14, 18));
        output2.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                outputWireMouseClicked(evt);
            }
        });
        outputPanel.add(output2);

        output1.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        output1.setText(resourceMap.getString("output1.text")); // NOI18N
        output1.setBorder(javax.swing.BorderFactory.createEtchedBorder());
        output1.setName("output1"); // NOI18N
        output1.setPreferredSize(new java.awt.Dimension(14, 18));
        output1.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                outputWireMouseClicked(evt);
            }
        });
        outputPanel.add(output1);

        inoutputGroup.add(outputPanel, new org.netbeans.lib.awtextra.AbsoluteConstraints(190, 20, -1, -1));

        jPanel2.setName("jPanel2"); // NOI18N

        input1.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        input1.setText(resourceMap.getString("input1.text")); // NOI18N
        input1.setBorder(javax.swing.BorderFactory.createEtchedBorder());
        input1.setMaximumSize(new java.awt.Dimension(26, 18));
        input1.setMinimumSize(new java.awt.Dimension(26, 18));
        input1.setName("input1"); // NOI18N
        input1.setOpaque(true);
        input1.setPreferredSize(new java.awt.Dimension(26, 18));
        input1.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                inputWireMouseClicked(evt);
            }
        });
        jPanel2.add(input1);

        input2.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        input2.setText(resourceMap.getString("input2.text")); // NOI18N
        input2.setBorder(javax.swing.BorderFactory.createEtchedBorder());
        input2.setMaximumSize(new java.awt.Dimension(26, 18));
        input2.setMinimumSize(new java.awt.Dimension(26, 18));
        input2.setName("input2"); // NOI18N
        input2.setOpaque(true);
        input2.setPreferredSize(new java.awt.Dimension(26, 18));
        input2.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                inputWireMouseClicked(evt);
            }
        });
        jPanel2.add(input2);

        input3.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        input3.setText(resourceMap.getString("input3.text")); // NOI18N
        input3.setBorder(javax.swing.BorderFactory.createEtchedBorder());
        input3.setMaximumSize(new java.awt.Dimension(26, 18));
        input3.setMinimumSize(new java.awt.Dimension(26, 18));
        input3.setName("input3"); // NOI18N
        input3.setOpaque(true);
        input3.setPreferredSize(new java.awt.Dimension(26, 18));
        input3.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                inputWireMouseClicked(evt);
            }
        });
        jPanel2.add(input3);

        input4.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
        input4.setText(resourceMap.getString("input4.text")); // NOI18N
        input4.setBorder(javax.swing.BorderFactory.createEtchedBorder());
        input4.setMaximumSize(new java.awt.Dimension(26, 18));
        input4.setMinimumSize(new java.awt.Dimension(26, 18));
        input4.setName("input4"); // NOI18N
        input4.setOpaque(true);
        input4.setPreferredSize(new java.awt.Dimension(26, 18));
        input4.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                inputWireMouseClicked(evt);
            }
        });
        jPanel2.add(input4);

        inoutputGroup.add(jPanel2, new org.netbeans.lib.awtextra.AbsoluteConstraints(220, 300, -1, 30));

        imagePanel.setBackground(resourceMap.getColor("imagePanel.background")); // NOI18N
        imagePanel.setMaximumSize(new java.awt.Dimension(350, 250));
        imagePanel.setMinimumSize(new java.awt.Dimension(350, 250));
        imagePanel.setName("imagePanel"); // NOI18N
        imagePanel.setPreferredSize(new java.awt.Dimension(350, 250));

        org.jdesktop.layout.GroupLayout imagePanelLayout = new org.jdesktop.layout.GroupLayout(imagePanel);
        imagePanel.setLayout(imagePanelLayout);
        imagePanelLayout.setHorizontalGroup(
            imagePanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(0, 350, Short.MAX_VALUE)
        );
        imagePanelLayout.setVerticalGroup(
            imagePanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(0, 250, Short.MAX_VALUE)
        );

        inoutputGroup.add(imagePanel, new org.netbeans.lib.awtextra.AbsoluteConstraints(10, 50, 350, 250));

        graphGroup.setBorder(javax.swing.BorderFactory.createTitledBorder(resourceMap.getString("graphGroup.border.title"))); // NOI18N
        graphGroup.setMaximumSize(new java.awt.Dimension(345, 191));
        graphGroup.setMinimumSize(new java.awt.Dimension(345, 191));
        graphGroup.setName("graphGroup"); // NOI18N

        graphTitle.setText(resourceMap.getString("graph.title.input")); // NOI18N
        graphTitle.setName("graphTitle"); // NOI18N

        lineGraph.setBackground(resourceMap.getColor("lineGraph.background")); // NOI18N
        lineGraph.setBorder(javax.swing.BorderFactory.createLineBorder(resourceMap.getColor("lineGraph.border.lineColor"))); // NOI18N
        lineGraph.setMaximumSize(new java.awt.Dimension(250, 50));
        lineGraph.setMinimumSize(new java.awt.Dimension(250, 50));
        lineGraph.setName("lineGraph"); // NOI18N
        lineGraph.setPreferredSize(new java.awt.Dimension(250, 50));

        org.jdesktop.layout.GroupLayout lineGraphLayout = new org.jdesktop.layout.GroupLayout(lineGraph);
        lineGraph.setLayout(lineGraphLayout);
        lineGraphLayout.setHorizontalGroup(
            lineGraphLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(0, 285, Short.MAX_VALUE)
        );
        lineGraphLayout.setVerticalGroup(
            lineGraphLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(0, 48, Short.MAX_VALUE)
        );

        thresholdPanel.setName("thresholdPanel"); // NOI18N
        thresholdPanel.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.RIGHT, 3, 3));

        thresholdLabel.setText(resourceMap.getString("thresholdLabel.text")); // NOI18N
        thresholdLabel.setName("thresholdLabel"); // NOI18N
        thresholdPanel.add(thresholdLabel);

        thresholdSlider.setMajorTickSpacing(5);
        thresholdSlider.setMaximum(255);
        thresholdSlider.setMinorTickSpacing(1);
        thresholdSlider.setName("thresholdSlider"); // NOI18N
        thresholdSlider.setPreferredSize(new java.awt.Dimension(150, 25));
        thresholdSlider.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                triggerValueChanged(evt);
            }
        });
        thresholdPanel.add(thresholdSlider);

        thresholdValue.setHorizontalAlignment(javax.swing.JTextField.RIGHT);
        thresholdValue.setText(resourceMap.getString("thresholdValue.text")); // NOI18N
        thresholdValue.setMaximumSize(new java.awt.Dimension(30, 20));
        thresholdValue.setMinimumSize(new java.awt.Dimension(30, 20));
        thresholdValue.setName("thresholdValue"); // NOI18N
        thresholdValue.setPreferredSize(new java.awt.Dimension(30, 20));
        thresholdValue.addFocusListener(new java.awt.event.FocusAdapter() {
            public void focusLost(java.awt.event.FocusEvent evt) {
                triggerNumberChanged(evt);
            }
        });
        thresholdPanel.add(thresholdValue);

        marginPanel.setName("marginPanel"); // NOI18N
        marginPanel.setPreferredSize(new java.awt.Dimension(291, 31));
        marginPanel.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.RIGHT, 3, 3));

        marginLabel.setText(resourceMap.getString("marginLabel.text")); // NOI18N
        marginLabel.setName("marginLabel"); // NOI18N
        marginPanel.add(marginLabel);

        marginSlider.setMajorTickSpacing(5);
        marginSlider.setMaximum(127);
        marginSlider.setMinorTickSpacing(1);
        marginSlider.setToolTipText(resourceMap.getString("marginSlider.toolTipText")); // NOI18N
        marginSlider.setName("marginSlider"); // NOI18N
        marginSlider.setPreferredSize(new java.awt.Dimension(150, 25));
        marginSlider.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                marginValueChanged(evt);
            }
        });
        marginPanel.add(marginSlider);

        marginValue.setHorizontalAlignment(javax.swing.JTextField.RIGHT);
        marginValue.setText(resourceMap.getString("marginValue.text")); // NOI18N
        marginValue.setMaximumSize(new java.awt.Dimension(30, 20));
        marginValue.setMinimumSize(new java.awt.Dimension(30, 20));
        marginValue.setName("marginValue"); // NOI18N
        marginValue.setPreferredSize(new java.awt.Dimension(30, 20));
        marginValue.addFocusListener(new java.awt.event.FocusAdapter() {
            public void focusLost(java.awt.event.FocusEvent evt) {
                marginNumberChanged(evt);
            }
        });
        marginPanel.add(marginValue);

        javax.swing.ActionMap actionMap = org.jdesktop.application.Application.getInstance(nl.lemval.nododue.NodoDueManager.class).getContext().getActionMap(MonitorPanel.class, this);
        wireCheck.setAction(actionMap.get("wireTickAction")); // NOI18N
        wireCheck.setText(resourceMap.getString("graph.wire.input")); // NOI18N
        wireCheck.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
        wireCheck.setHorizontalTextPosition(javax.swing.SwingConstants.LEFT);
        wireCheck.setMaximumSize(new java.awt.Dimension(150, 22));
        wireCheck.setMinimumSize(new java.awt.Dimension(150, 22));
        wireCheck.setName("wireCheck"); // NOI18N
        wireCheck.setPreferredSize(new java.awt.Dimension(150, 22));

        typePanel.setName("typePanel"); // NOI18N
        typePanel.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.RIGHT));

        typeLabel.setText(resourceMap.getString("typeLabel.text")); // NOI18N
        typeLabel.setName("typeLabel"); // NOI18N
        typePanel.add(typeLabel);

        typeSelection.setModel(typeSelectionModel);
        typeSelection.setName("typeSelection"); // NOI18N
        typeSelection.addItemListener(new java.awt.event.ItemListener() {
            public void itemStateChanged(java.awt.event.ItemEvent evt) {
                typeSelectionItemStateChanged(evt);
            }
        });
        typePanel.add(typeSelection);

        org.jdesktop.layout.GroupLayout graphGroupLayout = new org.jdesktop.layout.GroupLayout(graphGroup);
        graphGroup.setLayout(graphGroupLayout);
        graphGroupLayout.setHorizontalGroup(
            graphGroupLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(graphGroupLayout.createSequentialGroup()
                .add(graphGroupLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                    .add(graphGroupLayout.createSequentialGroup()
                        .addContainerGap()
                        .add(graphTitle, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 151, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                        .add(18, 18, 18)
                        .add(wireCheck, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 118, Short.MAX_VALUE))
                    .add(graphGroupLayout.createSequentialGroup()
                        .addContainerGap()
                        .add(typePanel, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 287, Short.MAX_VALUE))
                    .add(graphGroupLayout.createSequentialGroup()
                        .addContainerGap()
                        .add(lineGraph, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 287, Short.MAX_VALUE))
                    .add(graphGroupLayout.createSequentialGroup()
                        .add(10, 10, 10)
                        .add(graphGroupLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                            .add(org.jdesktop.layout.GroupLayout.TRAILING, thresholdPanel, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 289, Short.MAX_VALUE)
                            .add(marginPanel, 0, 0, Short.MAX_VALUE))))
                .addContainerGap())
        );
        graphGroupLayout.setVerticalGroup(
            graphGroupLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(graphGroupLayout.createSequentialGroup()
                .add(graphGroupLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                    .add(graphTitle)
                    .add(wireCheck, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(lineGraph, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(thresholdPanel, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(marginPanel, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(typePanel, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        refreshGroup.setBorder(javax.swing.BorderFactory.createTitledBorder(resourceMap.getString("refreshGroup.border.title"))); // NOI18N
        refreshGroup.setName("refreshGroup"); // NOI18N
        refreshGroup.setLayout(new java.awt.GridLayout(2, 0));

        jPanel1.setName("jPanel1"); // NOI18N
        jPanel1.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT));

        rrCheck.setAction(actionMap.get("refreshTickAction")); // NOI18N
        rrCheck.setText(resourceMap.getString("rrCheck.text")); // NOI18N
        rrCheck.setName("rrCheck"); // NOI18N
        jPanel1.add(rrCheck);

        rrSlider.setMajorTickSpacing(5);
        rrSlider.setMinimum(1);
        rrSlider.setMinorTickSpacing(1);
        rrSlider.setValue(25);
        rrSlider.setName("rrSlider"); // NOI18N
        rrSlider.setPreferredSize(new java.awt.Dimension(100, 25));
        rrSlider.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                refreshRateValueChanged(evt);
            }
        });
        jPanel1.add(rrSlider);

        rrValue.setHorizontalAlignment(javax.swing.JTextField.RIGHT);
        rrValue.setText(resourceMap.getString("rrValue.text")); // NOI18N
        rrValue.setMaximumSize(new java.awt.Dimension(30, 20));
        rrValue.setMinimumSize(new java.awt.Dimension(30, 20));
        rrValue.setName("rrValue"); // NOI18N
        rrValue.setPreferredSize(new java.awt.Dimension(30, 20));
        rrValue.addFocusListener(new java.awt.event.FocusAdapter() {
            public void focusLost(java.awt.event.FocusEvent evt) {
                refreshRateNumberChanged(evt);
            }
        });
        jPanel1.add(rrValue);

        rrLabel.setText(resourceMap.getString("rrLabel.text")); // NOI18N
        rrLabel.setName("rrLabel"); // NOI18N
        jPanel1.add(rrLabel);

        refreshGroup.add(jPanel1);

        jPanel3.setName("jPanel3"); // NOI18N
        jPanel3.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT));

        ververs.setAction(actionMap.get("refreshNow")); // NOI18N
        ververs.setName("ververs"); // NOI18N
        jPanel3.add(ververs);

        refreshGroup.add(jPanel3);

        org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(layout.createSequentialGroup()
                .addContainerGap()
                .add(inoutputGroup, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 373, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING, false)
                    .add(refreshGroup, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .add(graphGroup, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 323, Short.MAX_VALUE))
                .addContainerGap(org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(layout.createSequentialGroup()
                .addContainerGap()
                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                    .add(layout.createSequentialGroup()
                        .add(graphGroup, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(refreshGroup, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
                    .add(inoutputGroup, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 338, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
                .addContainerGap(34, Short.MAX_VALUE))
        );
    }// </editor-fold>//GEN-END:initComponents

    private void inputWireMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_inputWireMouseClicked
        changeGraph(evt.getComponent().getName(), Type.Input);
    }//GEN-LAST:event_inputWireMouseClicked

    private void refreshRateValueChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_refreshRateValueChanged
        if (rrSlider.getValueIsAdjusting() == false) {
            int value = rrSlider.getValue();
            double res = value / 2.0;
            if (res >= 10) {
                rrValue.setText(String.valueOf((int) res));
            } else {
                rrValue.setText(String.valueOf(res));
            }
            refreshTickAction();
        }
    }//GEN-LAST:event_refreshRateValueChanged

    private void triggerValueChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_triggerValueChanged
        if (thresholdSlider.getValueIsAdjusting() == false) {
            updateTooltips();
            updateThreshold();
        }
    }//GEN-LAST:event_triggerValueChanged

    private void marginValueChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_marginValueChanged
        if (marginSlider.getValueIsAdjusting() == false) {
            updateTooltips();
            updateMargin();
        }
    }//GEN-LAST:event_marginValueChanged

    private void refreshRateNumberChanged(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_refreshRateNumberChanged
        String txt = rrValue.getText();
        int value = rrSlider.getValue();
        try {
            value = (int) Double.parseDouble(txt) * 2;
            if (value > rrSlider.getMaximum()) {
                value = rrSlider.getMaximum();
            }
            if (value < rrSlider.getMinimum()) {
                value = rrSlider.getMinimum();
            }
        } catch (NumberFormatException e) {
        }
        rrSlider.setValue(value);
        // Former triggers the actual action
    }//GEN-LAST:event_refreshRateNumberChanged

    private void triggerNumberChanged(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_triggerNumberChanged
        String txt = thresholdValue.getText();
        int value = thresholdSlider.getValue();
        try {
            value = Integer.parseInt(txt);
            if (value > thresholdSlider.getMaximum()) {
                value = thresholdSlider.getMaximum();
            }
            if (value < thresholdSlider.getMinimum()) {
                value = thresholdSlider.getMinimum();
            }
        } catch (NumberFormatException e) {
        }
        thresholdSlider.setValue(value);
        // Former triggers the actual action
    }//GEN-LAST:event_triggerNumberChanged

    private void marginNumberChanged(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_marginNumberChanged
        String txt = marginValue.getText();
        int value = marginSlider.getValue();
        try {
            value = Integer.parseInt(txt);
            if (value > marginSlider.getMaximum()) {
                value = marginSlider.getMaximum();
            }
            if (value < marginSlider.getMinimum()) {
                value = marginSlider.getMinimum();
            }
        } catch (NumberFormatException e) {
        }
        marginSlider.setValue(value);
        // Former triggers the actual action
    }//GEN-LAST:event_marginNumberChanged

    private void outputWireMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_outputWireMouseClicked
        changeGraph(evt.getComponent().getName(), Type.Output);
    }//GEN-LAST:event_outputWireMouseClicked

    private void typeSelectionItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_typeSelectionItemStateChanged
        if (selectedWire != null) {
            selectedWire.setSignalType((InputRange) typeSelection.getSelectedItem());
        }
        updateTooltips();
    }//GEN-LAST:event_typeSelectionItemStateChanged

    private JPanel createImagePanel() {
        return new ArduinoImagePanel();
    }

    private void changeGraph(String cName, Type type) {
        Type prev = (selectedWire == null ? null : selectedWire.getType());

        int idx = Integer.parseInt(cName.substring(cName.length() - 1));
        selectedWire = allWires.get(idx, type);
        Type now = (selectedWire == null ? null : selectedWire.getType());

        if (now.equals(prev) == false) {
            updateGraphState();
        }

        if (now == Type.Output) {
            graphTitle.setText(getResourceString("graph.title.outputMessage", idx));
        } else {
            graphTitle.setText(getResourceString("graph.title.inputMessage", idx));
            if (selectedWire != null && selectedWire.getSignalType() != null) {
                typeSelection.setSelectedItem(selectedWire.getSignalType());
            }
        }

        updateScreen();
    }

    private void updateGraphState() {
        Type state = (selectedWire == null ? null : selectedWire.getType());

        if (state == Type.Input) {
            wireCheck.setText(getResourceString("graph.wire.input"));
            thresholdSlider.setEnabled(true);
            thresholdValue.setEnabled(true);
            marginSlider.setEnabled(true);
            marginValue.setEnabled(true);
            typeSelection.setEnabled(true);
        } else {
            wireCheck.setText(getResourceString("graph.wire.output"));
            thresholdSlider.setEnabled(false);
            thresholdValue.setEnabled(false);
            marginSlider.setEnabled(false);
            marginValue.setEnabled(false);
            typeSelection.setEnabled(false);
        }
    }

    private void updateScreen() {
        if (selectedWire != null) {
            updateGraph();
        }
        output1.setText(allWires.get(1, Type.Output).getActive());
        output2.setText(allWires.get(2, Type.Output).getActive());
        output3.setText(allWires.get(3, Type.Output).getActive());
        output4.setText(allWires.get(4, Type.Output).getActive());

        final Wire wire1 = allWires.get(1, Type.Input);
        final Wire wire2 = allWires.get(2, Type.Input);
        final Wire wire3 = allWires.get(3, Type.Input);
        final Wire wire4 = allWires.get(4, Type.Input);

        input1.setText(wire1.getLastValue());
        input2.setText(wire2.getLastValue());
        input3.setText(wire3.getLastValue());
        input4.setText(wire4.getLastValue());

        InputRange ir = (InputRange) typeSelection.getSelectedItem();
        if (wire1.getLastData() != null) {
            input1.setToolTipText(ir.getDescription(wire1.getLastData().getValue()));
        }
        if (wire2.getLastData() != null) {
            input2.setToolTipText(ir.getDescription(wire2.getLastData().getValue()));
        }
        if (wire3.getLastData() != null) {
            input3.setToolTipText(ir.getDescription(wire3.getLastData().getValue()));
        }
        if (wire4.getLastData() != null) {
            input4.setToolTipText(ir.getDescription(wire4.getLastData().getValue()));
        }
    }

    protected void updateGraph() {
        // Update the graph
        WireData data = selectedWire.getLastData();
        if (data != null) {
            if (marginSlider.isEnabled()) {
                marginSlider.setValue(data.getMargin());
            }
            if (thresholdSlider.isEnabled()) {
                thresholdSlider.setValue(data.getThreshold());
            }
            wireCheck.setSelected(data.isState());
            ((WireGraphPanel) lineGraph).setData(selectedWire);
            lineGraph.repaint();
        }
    }

    private void updateMargin() {
        if (NodoDueManager.hasConnection()) {
            // Only set the new margin on actual change
            WireData data = selectedWire.getLastData();
            if (data == null || marginSlider.getValue() != data.getMargin()) {
                SerialCommunicator comm =
                        NodoDueManager.getApplication().getSerialCommunicator();
                try {
                    CommandInfo ci = CommandLoader.get(Name.WiredSmittTrigger);
                    comm.send(new NodoCommand(ci,
                            String.valueOf(selectedWire.getChannel()),
                            String.valueOf(marginSlider.getValue())));
                    comm.waitCommand(50, 500);
                } catch (Exception e) {
                    getListener().showStatusMessage(getResourceString("update_fail.margin", e.getMessage()));
                }
            }
        }
    }

    private void updateThreshold() {
        if (NodoDueManager.hasConnection()) {
            // Only set the new margin on actual change
            WireData data = selectedWire.getLastData();
            if (data == null || thresholdSlider.getValue() != data.getThreshold()) {
                SerialCommunicator comm =
                        NodoDueManager.getApplication().getSerialCommunicator();
                try {
                    CommandInfo ci = CommandLoader.get(Name.WiredThreshold);
                    comm.send(new NodoCommand(ci,
                            String.valueOf(selectedWire.getChannel()),
                            String.valueOf(thresholdSlider.getValue())));
                    comm.waitCommand(50, 500);
                } catch (Exception e) {
                    getListener().showStatusMessage(getResourceString("update_fail.threshold", e.getMessage()));
                }
            }
        }
    }

    private void downloadAndRefresh() {
        NodoDueManager app = NodoDueManager.getApplication();
        if (!app.hasConnection(false)) {
            return;
        }
        TaskService ts = app.getContext().getTaskService();
        refreshTask = new RefreshTask(app);
        ts.execute(refreshTask);
    }

    private void updateTooltips() {
        InputRange ir = (InputRange) typeSelection.getSelectedItem();

        String thresholdText = ir.getDescription(thresholdSlider.getValue());
        thresholdSlider.setToolTipText(thresholdText);
        thresholdValue.setToolTipText(thresholdText);
        thresholdValue.setText(String.valueOf(thresholdSlider.getValue()));

        String marginText = ir.getDescription(marginSlider.getValue());
        marginSlider.setToolTipText(marginText);
        marginValue.setToolTipText(marginText);
        marginValue.setText(String.valueOf(marginSlider.getValue()));
    }

    private class RefreshTask extends org.jdesktop.application.Task<Object, Void> {

        RefreshTask(org.jdesktop.application.Application app) {
            super(app);
            Wire.setMaxLength(lineGraph.getWidth());
        }

        @Override
        protected Object doInBackground() {
            if (NodoDueManager.hasConnection() == false) {
                return null;
            }
            Collection<CommandInfo> cis = new ArrayList<CommandInfo>();
            CommandInfo wiredOut = CommandLoader.get(Name.WiredOut);
            CommandInfo wiredPul = CommandLoader.get(Name.WiredPullup);
            CommandInfo wiredStr = CommandLoader.get(Name.WiredSmittTrigger);
            CommandInfo wiredThd = CommandLoader.get(Name.WiredThreshold);
            CommandInfo wiredAna = CommandLoader.get(Name.WiredAnalog);
            cis.add(wiredOut);
            cis.add(wiredPul);
            cis.add(wiredStr);
            cis.add(wiredThd);
            cis.add(wiredAna);
//	    System.out.println("Refreshing...");
            Collection<NodoSetting> settings = NodoSettingRetriever.getSettings(cis);

            WireData[] data = new WireData[8];
            for (int i = 0; i < data.length; i++) {
                data[i] = new WireData();
            }

            for (NodoSetting nodoSetting : settings) {
                int idx = Integer.parseInt(nodoSetting.getAttributeData1());
                String value = nodoSetting.getAttributeData2();
                Name name = nodoSetting.getInfo().getNameElement();
                if (name == null) {
                    System.out.println("Oeps on " + nodoSetting);
                    continue;
                }

                switch (name) {
                    case WiredOut:
                        WireData wd = data[idx - 1 + 4];
                        wd.setState("On".equals(value));
                        wd.setValue(wd.isState() ? 255 : 0);
                        break;
                    case WiredPullup:
                        data[idx - 1].setState("On".equals(value));
                        break;
                    case WiredSmittTrigger:
                        data[idx - 1].setMargin(Integer.parseInt(value));
                        break;
                    case WiredThreshold:
                        data[idx - 1].setThreshold(Integer.parseInt(value));
                        break;
                    case WiredAnalog:
                        data[idx - 1].setValue(Integer.parseInt(value));
                        break;
                }
            }
            return data;
        }

        @Override
        protected void succeeded(Object result) {
            if (result == null) {
                return;
            }

            WireData[] data = (WireData[]) result;
            Wire wire = null;

            for (int i = 0; i < 4; i++) {
                wire = allWires.get(i + 1, Type.Input);
                wire.addData(data[i]);
            }
            for (int i = 4; i < 8; i++) {
                wire = allWires.get(i + 1 - 4, Type.Output);
                wire.addData(data[i]);
            }
            updateScreen();
        }
    }

    @Action
    public void refreshTickAction() {
        if (refreshTimer == null) {
            // Interval from 1..100, interval .5 seconds
            int time = rrSlider.getValue() * 500;
            refreshTimer = new Timer(time, new ActionListener() {

                public void actionPerformed(ActionEvent e) {
                    downloadAndRefresh();
                }
            });
            refreshTimer.setRepeats(true);
        }

        if (rrCheck.isSelected()) {
            if (refreshTimer.isRunning()) {
                refreshTimer.stop();
            }
            refreshTimer.setDelay(rrSlider.getValue() * 500);
            markDisabled(true);
            refreshTimer.start();
            downloadAndRefresh();
        } else {
            refreshTimer.stop();
            markDisabled(false);
        }
    }

    private void markDisabled(boolean disable) {
        ververs.setEnabled(!disable);
        wireCheck.setEnabled(!disable);
        if (disable) {
            thresholdSlider.setEnabled(false);
            thresholdValue.setEnabled(false);
            marginSlider.setEnabled(false);
            marginValue.setEnabled(false);
        } else {
            updateGraphState();
        }
    }

//    private void enableContainer(Container base, boolean enable) {
//	Component[] components = base.getComponents();
//	for (int i = 0; i < components.length; i++) {
//	    Component component = components[i];
//	    component.setEnabled(enable);
//	    if ( component instanceof Container ) {
//		enableContainer((Container)component, enable);
//	    }
//	}
//    }
    @Action
    public void wireTickAction() {
        CommandInfo ci = null;
        String val = null;
        String idx = null;
        if (selectedWire != null) {
            idx = "" + selectedWire.getChannel();
            if (selectedWire.getType() == Type.Input) {
                // Switch pullup
                ci = CommandLoader.get(Name.WiredPullup);
                val = wireCheck.isSelected() ? "On" : "Off";
            } else {
                // Switch output
                ci = CommandLoader.get(Name.WiredOut);
                val = wireCheck.isSelected() ? "On" : "Off";
            }
        }
        if (NodoDueManager.hasConnection() == false) {
            return;
        }
        SerialCommunicator comm =
                NodoDueManager.getApplication().getSerialCommunicator();
        try {
            comm.send(new NodoCommand(ci, idx, val));
            comm.waitCommand();
        } catch (Exception e) {
            getListener().showStatusMessage(getResourceString("update_fail.wireChange", e.getMessage()));
        }
    }

    @Action
    public void refreshNow() {
        downloadAndRefresh();
    }
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JPanel graphGroup;
    private javax.swing.JLabel graphTitle;
    private javax.swing.JPanel imagePanel;
    private javax.swing.JPanel inoutputGroup;
    private javax.swing.JLabel input1;
    private javax.swing.JLabel input2;
    private javax.swing.JLabel input3;
    private javax.swing.JLabel input4;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JPanel jPanel2;
    private javax.swing.JPanel jPanel3;
    private javax.swing.JPanel lineGraph;
    private javax.swing.JLabel marginLabel;
    private javax.swing.JPanel marginPanel;
    private javax.swing.JSlider marginSlider;
    private javax.swing.JTextField marginValue;
    private javax.swing.JLabel output1;
    private javax.swing.JLabel output2;
    private javax.swing.JLabel output3;
    private javax.swing.JLabel output4;
    private javax.swing.JPanel outputPanel;
    private javax.swing.JPanel refreshGroup;
    private javax.swing.JCheckBox rrCheck;
    private javax.swing.JLabel rrLabel;
    private javax.swing.JSlider rrSlider;
    private javax.swing.JTextField rrValue;
    private javax.swing.JLabel thresholdLabel;
    private javax.swing.JPanel thresholdPanel;
    private javax.swing.JSlider thresholdSlider;
    private javax.swing.JTextField thresholdValue;
    private javax.swing.JLabel typeLabel;
    private javax.swing.JPanel typePanel;
    private javax.swing.JComboBox typeSelection;
    private javax.swing.JButton ververs;
    private javax.swing.JCheckBox wireCheck;
    // End of variables declaration//GEN-END:variables
}
